/*******************************************************************************
* COPYRIGHT LIPUJUN TECH CO.,LTD
********************************************************************************
* 文件名称:  mqttMsmgCmd.c
* 功能描述:
* 使用说明:  无
* 文件作者:  LIPUJUN
* 编写日期:  2018/11/28
* 修改历史:
* 修改版本  修改日期       修改人   修改内容
* ------------------------------------------------------------------------------
  01a       2018/11/28       李普军   创建
*******************************************************************************/

/******************************* 包含文件声明 ********************************/
#include "msg_core.h"
#include "user_core.h"
#include "link.h"
#include <strings.h>
#include <unistd.h>

MSG_QUEUE_BD_DESC recvMsgDesc;
MSG_QUEUE_BD_DESC sendMsgDesc;
extern AIR_APP_INFO_T stMqttMsgInfo;
/*******************************************************************************
*   函数名称: tcpMsgInit
*   功    能: TCP 通信 初始化
*   函数类型:
*   参    数: 无
*   参数名称       类  型                   输入/输出         描述
*   函数返回: OK 或失败的错误码
*   说    明:
*******************************************************************************/

INT32 msgBdInit (MSG_QUEUE_BD_DESC *pMsgDesc)
{
    CHAR *data;
    UINT32 ix = 0;

    /* 队列大小 */
    pMsgDesc->msgQ = (MSG_DATA_T *) malloc (sizeof (MSG_DATA_T) * MSG_QUEUE_MAX_NUM);
    if (NULL == pMsgDesc->msgQ)
    {
        Error ("msgBDInit, (NULL == pMsgDesc->msgQ), malloc fail .");
        return ERROR;
    }
    bzero ((char *)pMsgDesc->msgQ, sizeof (MSG_DATA_T) * MSG_QUEUE_MAX_NUM);

    /* 数据区大小 */
    data = (CHAR *) malloc (MSG_QUEUE_DATA_LEN * MSG_QUEUE_MAX_NUM);
    if (NULL == data)
    {
        Error ("msgBDInit, (NULL == buf), malloc fail .");
        return ERROR;
    }
    bzero ((char *)data, MSG_QUEUE_DATA_LEN * MSG_QUEUE_MAX_NUM);
	
    /* 初始化队列 */
    for(ix=0; ix<MSG_QUEUE_MAX_NUM; ix++){
        pMsgDesc->msgQ[ix].data = data + ix * MSG_QUEUE_DATA_LEN;
        pMsgDesc->msgQ[ix].len = 0;
	pMsgDesc->msgQ[ix].type = CMD_NULL;
//	pMsgDesc->msgQ[ix].ver = APP_SUPPORT_MSG_VER;
	pMsgDesc->msgQ[ix].assure = 0;
    }

    return OK;
}
void msgBdDestroy (MSG_QUEUE_BD_DESC *pMsgDesc)
{
    if(pMsgDesc == NULL)
        return;
    if(pMsgDesc->msgQ && pMsgDesc->msgQ[0].data)
        free(pMsgDesc->msgQ[0].data);
    if(pMsgDesc->msgQ)
        free(pMsgDesc->msgQ);
    return;    
}
INT32 msg_init(void)
{
    INT32 ret = ERROR;
    ret = msgBdInit (&recvMsgDesc);
    if(ret == OK)
    	ret = msgBdInit (&sendMsgDesc);
    return ret;	
}
/*******************************************************************************
*   函数名称: msgBdWrite
*   功    能: 将 TCP 接收到的数据保存到缓存池
*   函数类型:
*   参    数:
*   参数名称       类  型                   输入/输出         描述
*     pMsgDesc      MSG_BD_DESC *              IN              bd描述符
*     buf           UINT8 *                    IN               数据
*     len           UINT32                     IN               数据长度
*
*   函数返回: OK 或失败的错误码
*   说    明:
*******************************************************************************/
INT32 msgBdWrite (UINT32 type, MSG_QUEUE_BD_DESC *pMsgDesc, CHAR *buf, UINT32 len,UINT8 assure)
{
	//msgBdWrite (type, &mqttRecvMsgDesc, buf, len, 0);
    UINT32 wPt = 0;
    if (len > MSG_QUEUE_DATA_LEN)
    {
        Error ("msgBdWrite, len=0x%x !", len);
        return ERROR;
    }

    wPt = pMsgDesc->wPt;
    wPt ++;

    if(wPt == pMsgDesc->rPt)
    {
        pMsgDesc->txFullCount ++;
        return ERROR;
    }

    memcpy ((void *)pMsgDesc->msgQ[pMsgDesc->wPt].data, (void *)buf, len);
    pMsgDesc->msgQ[pMsgDesc->wPt].len = len;
    pMsgDesc->msgQ[pMsgDesc->wPt].type = type;
    pMsgDesc->msgQ[pMsgDesc->wPt].assure = assure;
    //pMsgDesc->msgQ[pMsgDesc->wPt].ver = APP_SUPPORT_MSG_VER;

    pMsgDesc->wPt = (pMsgDesc->wPt + 1) % MSG_QUEUE_MAX_NUM;

    pMsgDesc->txCount ++;
    return OK;
}



/*******************************************************************************
*   函数名称: msgBdRead
*   功    能: 读取缓存池中的数据
*   函数类型:
*   参    数:
*   参数名称       类  型                   输入/输出         描述
*     pMsgDesc      MSG_BD_DESC *              IN              bd描述符
*     buf           UINT8 *                    OUT             数据
*     len           UINT32*                    OUT             数据长度
*
*   函数返回: OK 或失败的错误码
*   说    明:
*******************************************************************************/
INT32 msgBdRead (MSG_QUEUE_BD_DESC *pMsgDesc, MSG_DATA_T *data)
{
    UINT32 dataLen = 0;

   if(pMsgDesc->wPt == pMsgDesc->rPt)
    {
        data->len = 0;
        pMsgDesc->rxEmpCount ++;
        return ERROR;
    }

    dataLen = pMsgDesc->msgQ[pMsgDesc->rPt].len;

    if (dataLen > MSG_QUEUE_DATA_LEN)
    {
        data->len = 0;
        pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
        return ERROR;
    }

    data->len = dataLen;
    bcopy ((char *)pMsgDesc->msgQ[pMsgDesc->rPt].data, (char *)data->data, dataLen);	
    data->type = pMsgDesc->msgQ[pMsgDesc->rPt].type;
    data->ver = pMsgDesc->msgQ[pMsgDesc->rPt].ver;
    data->assure = pMsgDesc->msgQ[pMsgDesc->rPt].assure;
	
    //if(!pMsgDesc->msgQ[pMsgDesc->rPt].assure){
	bzero ((char *)pMsgDesc->msgQ[pMsgDesc->rPt].data, MSG_QUEUE_DATA_LEN);

	pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
	pMsgDesc->rxCount ++;
   // }
    return OK;
}
void msgBdClean(void)
{
   MSG_QUEUE_BD_DESC *pMsgDesc = &sendMsgDesc;

   UINT32 dataLen = 0;
   INT32 i = 0;
   
   for( i = 0 ; i < MSG_QUEUE_MAX_NUM;i++){
       if(pMsgDesc->wPt == pMsgDesc->rPt){          
           pMsgDesc->rxEmpCount ++;
           return ;
       }

        dataLen = pMsgDesc->msgQ[pMsgDesc->rPt].len;

        if (dataLen > MSG_QUEUE_DATA_LEN)
        {          
            pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
            continue;
        }
        bzero ((char *)pMsgDesc->msgQ[pMsgDesc->rPt].data, MSG_QUEUE_DATA_LEN);
        pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
	pMsgDesc->rxCount ++;   
    }
    return ;
}
INT32 msgBdRemove(MSG_QUEUE_BD_DESC *pMsgDesc)
{
    UINT32 dataLen = 0;

    if(pMsgDesc->wPt == pMsgDesc->rPt)
    {        
        pMsgDesc->rxEmpCount ++;
        return ERROR;
    }

    dataLen = pMsgDesc->msgQ[pMsgDesc->rPt].len;

    if (dataLen > MSG_QUEUE_DATA_LEN)
    {       
        pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
        return ERROR;
    }
    bzero ((char *)pMsgDesc->msgQ[pMsgDesc->rPt].data, MSG_QUEUE_DATA_LEN);
    pMsgDesc->msgQ[pMsgDesc->rPt].assure = 0;
    pMsgDesc->rPt = (pMsgDesc->rPt + 1) % MSG_QUEUE_MAX_NUM;
	
    pMsgDesc->rxCount++;
    return OK;
}
INT32 msgBdQuery(MSG_QUEUE_BD_DESC *pMsgDesc,UINT8 type)
{
    UINT32 dataLen = 0;

    if(pMsgDesc->wPt == pMsgDesc->rPt)
    {       
        pMsgDesc->rxEmpCount ++;
        return ERROR;
    }

    dataLen = pMsgDesc->msgQ[pMsgDesc->rPt].len;

    if (dataLen > MSG_QUEUE_DATA_LEN)
    {       
        return ERROR;
    }
    if(pMsgDesc->msgQ[pMsgDesc->rPt].type == type)
        return OK;
    return ERROR;
}
BOOL msgBdRecvUniq(UINT8 type)
{
    return (msgBdQuery(&recvMsgDesc ,type) == OK);
}
INT32 recvDataToMsgQ (UINT32 type, CHAR *buf, UINT32 len)
{
    INT32 ret = 0;


    ret = msgBdWrite (type, &recvMsgDesc, buf, len, 0);
    return (ret);
}
/*******************************************************************************
*   函数名称: msgSend
*   功    能: 发 数据
*   函数类型:
*   参    数:
*   参数名称       类  型                   输入/输出         描述
*     buf           UINT8 *                    IN               数据
*     len           UINT32                     IN               数据长度
*
*   函数返回: OK 或失败的错误码
*   说    明:
*******************************************************************************/
INT32 air_rcv_msg (UINT32 type, void *buf, int len)
{
    ((CHAR *)buf)[len] = 0;
    recvDataToMsgQ (type,(CHAR *)buf, (UINT32)len);
    return OK;
}

/*******************************************************************************
*   函数名称: msgSend
*   功    能: 发 数据
*   函数类型:
*   参    数:
*   参数名称       类  型                   输入/输出         描述
*     buf           UINT8 *                    IN               数据
*     len           UINT32                     IN               数据长度
*
*   函数返回: OK 或失败的错误码
*   说    明:
*******************************************************************************/
INT32 air_send_msg(UINT32 type,void *buf, UINT32 len, UINT8 assure)
{
   INT32 ret = 0;
   if(stMqttMsgInfo.link != IOT_STATUS_CONNECT && stMqttMsgInfo.regHostAck != MQTT_REG_HOST_MSG_OK)
	return ret;

   ret = msgBdWrite (type, &sendMsgDesc, (CHAR*)buf, len, assure);

   return (ret);
}

INT32 msgSend (UINT32 type,CHAR *buf, UINT32 len,UINT8 assure)
{
    INT32 ret = 0;
 
    sem_wait (&stMqttMsgInfo.msgSem);

    ret = msgBdWrite (type, &sendMsgDesc, (CHAR*)buf, len, assure);

    sem_post (&stMqttMsgInfo.msgSem);

    return (ret);
}

INT32 mqttMsgTaskSend (void)
{
    INT32 ret = 0;
    memset (stMqttMsgInfo.sData.data, 0x00, MSG_QUEUE_DATA_LEN);
    ret = msgBdRead (&sendMsgDesc, &stMqttMsgInfo.sData);

    if (OK != ret)
    {
        return (ret);
    }

    /* 消息队列中没有数据 */
    if (0 == stMqttMsgInfo.sData.len)
    {
        return ERROR;
    }
    else /* 消息处理 */
    {
	ret = link_sendMsg(&stMqttMsgInfo.sData);
	//if(ret > 0 && stMqttMsgInfo.sData.assure){
	   // msgBdRemove(&sendMsgDesc);
	//}
        //ret = mqttMsgSend (stMqttMsgInfo.sData);
    }

    return (ret);
}
/*
*接收消息处理函数
*/
INT32 mqttRecvDataProc_task (void *arg)
{
    INT32 ret = 0;

    while (1)
    {
        usleep (50000);
        memset (stMqttMsgInfo.rData.data, 0x00, MSG_QUEUE_DATA_LEN);
        ret = msgBdRead (&recvMsgDesc, &stMqttMsgInfo.rData);

        if (OK != ret){
            continue;
        }

        /* 消息队列中没有数据 */
        if (0 == stMqttMsgInfo.rData.len){
            continue;
        }else{ /* 消息处理 */
	    if(stMqttMsgInfo.rData.type > CMD_NULL && stMqttMsgInfo.rData.type < CMD_SIZE){
	        mqttMsgCmdRun (stMqttMsgInfo.rData.type, stMqttMsgInfo.rData.data, stMqttMsgInfo.rData.len);
	    }       
        }
    }

    return OK;
}

/******************************* 源文件结束 **********************************/
